package com.ktjiaoyu.server.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ktjiaoyu.server.mapper.MenuMapper;
import com.ktjiaoyu.server.mapper.MenuRoleMapper;
import com.ktjiaoyu.server.pojo.Admin;
import com.ktjiaoyu.server.pojo.Menu;
import com.ktjiaoyu.server.pojo.MenuRole;
import com.ktjiaoyu.server.service.IMenuService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author jjx
 * @since 2024-01-23
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {
    @Resource
    MenuMapper menuMapper;
    @Resource
    MenuRoleMapper menuRoleMapper;
    @Resource
    RedisTemplate<String,Object> redisTemplate;

    @Override
    public List<Menu> getMenusByAdminId() {
        Admin admin=(Admin)SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        //1.先从redis查询菜单
        ValueOperations<String, Object> ops = redisTemplate.opsForValue();
        List<Menu> list = (List<Menu>) ops.get("menu_" + admin.getId());
        //如果没有查询；就去数据库中查询；查到之后往redis里面存一份
        if(list==null||list.size()==0){
            list=menuMapper.getMenusByAdminId(admin.getId());
            ops.set("menu_" + admin.getId(),list);
        }
        //如果有查询，直接返回
        return list;
    }

    // 获取所有的菜单列表(非分页带层级关系用于绑定树形菜单控件)
    @Override
    public List<Menu> getAllMenuList() {
        // 1、获取所有的菜单列表
        List<Menu> menus = menuMapper.selectList(null);
        // 2、对获取到的菜单列表进行分层，即查询出每层菜单的子菜单列表
        List<Menu> oneLevelMenus = getLevelMenuList(menus);
        return oneLevelMenus;
    }

    // 查询出每层菜单的子菜单列表
    public List<Menu> getLevelMenuList(List<Menu> menuList) {
        // oneLevelMenus 为一级菜单列表
        List<Menu> oneLevelMenus = menuList.stream().filter((menu) -> {
            // 过滤出当前角色下的一级权限列表，之后再调用map对这个一级权限列表进行遍历
            return menu.getParentId() != null && menu.getParentId() == 1;
        }).map((oneLevelMenu) -> { // 调用map对这个一级权限列表进行遍历
            // 遍历一级权限得到一级权限下的二级权限。
            oneLevelMenu.setChildren(getChildrens(oneLevelMenu, menuList));
            return oneLevelMenu;
        }).collect(Collectors.toList());
        return oneLevelMenus;
    }

    /**
     * 得到当前权限下的子权限集合
     * @param oneLevelMenu 权限对象(比如一级或二级)
     * @param menuList 为当前角色所拥有的所有权限集合
     * @return 返回当前权限下的子权限列表
     */
    private List<Menu> getChildrens(Menu oneLevelMenu, List<Menu> menuList) {
        List<Menu> childMenuList = menuList.stream().filter((menu) ->
                // 过滤条件是：权限集合中menu对象的pid父级ID == 当前权限对象oneLevelMenu的ID
                // 实现将当前权限对象oneLevelMenu的子权限列表过滤出来，如果onLevelMenu为一级权限，
                // 那么就可以把这个一级权限下的二级权限给过滤出来。
                menu.getParentId() == oneLevelMenu.getId()
        ).map((sonMenu) -> {
            // 调用map方法，将过滤出来的子权限查询进行遍历。
            sonMenu.setChildren(getChildrens(sonMenu, menuList));
            return sonMenu;
        }).collect(Collectors.toList());
        return childMenuList;
    }

    @Override
    public String getMenuIdsByRoleId(Integer roleId) {
        return menuMapper.getMenuIdsByRoleId(roleId);
    }

    // 保存菜单信息
    @Override
    public boolean saveMenu(Menu menu) {
        if (menuMapper.insert(menu) > 0) {
            return true;
        }
        return false;
    }

    // 保存修改后的角色信息
    @Override
    public boolean updateMenu(Menu menu) {
        return menuMapper.updateById(menu) > 0 ? true : false;
    }

    @Override
    public void delMenuById(Integer id) {
        //1.删除角色菜单中间表（根据菜单id）
        menuRoleMapper.delete(new QueryWrapper<MenuRole>().eq("mid", id));
        //2.删除菜单表（根据菜单id
        menuMapper.deleteById(id);
    }

    //根据角色获取菜单列表
    @Override
    public List<Menu> getMenusWithRole() {
        return menuMapper.getMenusWithRole();
    }
}
